Hi SJH,
I see now there is a flaw where KFLOP on Resume clears CS0_StoppingState
and then immediately commands the motions. So there would be a small
window of time between feedhold clear and no motion. It isn't clear why
my test code doesn't show the issue. But that is the nature of such
issues. Calculating the new Trajectory does involve quite a bit of
calculation and can vary depending on circumstances. I don't see an
elegant solution. I'm still thinking the best solution it to wait for
the destination to be at the target position.
Regards
TK
On 2017-05-12 17:36, Hardy Family hardy.woodland.cypress@...
[DynoMotion] wrote:
> I tried adding a few WaitNextTimeSlice() calls then do another
> CheckDone(), and it works!
>
> So it looks like I need to be sure, to be sure.
>
> Regards,
> SJH
>
> On Fri, May 12, 2017 at 4:21 PM, Hardy Family
> <hardy.woodland.cypress@...> wrote:
>
>> It seems like sending a "StopImmediate 1" command from the PC, to
>> resume from a feed hold, is first setting CS0_StoppingState back to
>> zero, but for at least a short time thereafter, CheckDone() returns
>> 1. This causes it to break out of the wait loop.
>>
>> This is the code I am using to debug the wait:
>>
>> void wait_done_dbg(unsigned axis_mask)
>> {
>> unsigned i;
>> unsigned moving = axis_mask;
>> unsigned iam = axis_mask;
>> int css = CS0_StoppingState;
>> double lmdx = ch0->LastMotionDest;
>> double lmdy = ch1->LastMotionDest;
>> double lmdz = ch2->LastMotionDest;
>> int ess = *supe->estop_state;
>> int enab = chan[0].Enable | chan[1].Enable<<1 |
>> chan[2].Enable<<2;
>> int e;
>>
>> printf("WD: Entry: mask=%X, lmd=[%.0f,%.0f,%.0f], ss=%d\n", iam,
>> lmdx, lmdy, lmdz, ess);
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDoneFH(i))
>> axis_mask &= ~(1u<<i);
>> if (axis_mask != iam) {
>> printf("WD: axis_mask now %X\n", axis_mask);
>> iam = axis_mask;
>> }
>> if (CS0_StoppingState != css) {
>> printf("WD: stop state now %d\n", CS0_StoppingState);
>> css = CS0_StoppingState;
>> }
>> if (ch0->LastMotionDest != lmdx) {
>> printf("WD: lmd[x] now %.0f\n", ch0->LastMotionDest);
>> lmdx = ch0->LastMotionDest;
>> }
>> if (ch1->LastMotionDest != lmdy) {
>> printf("WD: lmd[y] now %.0f\n", ch1->LastMotionDest);
>> lmdy = ch1->LastMotionDest;
>> }
>> if (ch2->LastMotionDest != lmdz) {
>> printf("WD: lmd[z] now %.0f\n", ch2->LastMotionDest);
>> lmdz = ch2->LastMotionDest;
>> }
>> if (*supe->estop_state != ess) {
>> printf("WD: Estop state now %d\n", *supe->estop_state);
>> ess = *supe->estop_state;
>> }
>> e = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
>> if (e != enab) {
>> printf("WD: Axis enable mask now %X\n", e);
>> enab = e;
>> }
>> }
>> printf("WD: Exit: pos=[%.0f,%.0f,%.0f]\n", ch0->Position,
>> ch1->Position, ch2->Position);
>> if (moving & 1 && fast_fabs(lmdx-ch0->Position) > 100. ||
>> moving & 2 && fast_fabs(lmdy-ch1->Position) > 100. ||
>> moving & 4 && fast_fabs(lmdz-ch2->Position) > 100.)
>> printf("!!!! which ain't even close!\n");
>> }
>>
>> and the console log gets the following for an XY move:
>>
>> + 0 k: WD: Entry: mask=3, lmd=[16500,-94367,11980], ss=0
>> + 0 k: WD: axis_mask now 1
>> + 643 k: WD: stop state now 2
>> + 189 k: WD: stop state now 4
>> + 1804 k: WD: axis_mask now 0
>> + 0 k: WD: stop state now 0
>> + 0 k: WD: Exit: pos=[-56063,-94366,11980]
>> + 0 k: !!!! which ain't even close!
>>
>> (I add the '+ n k:' prefix to print the number of ms since last log
>> print, as seen by the PC.)
>>
>> On the 3rd line, I press feed hold (StopImmediate 0) and the
>> stopping state ends up at 4 with the axis halted. Then at line 5 I
>> release the f/h, and it sees axis_mask==0, which is because
>> CheckDone() returned 1, and at the same time stop state is back to
>> 0. As the next line shows, it didn't end up at the destination.
>>
>> So either the kflop forgot to set CheckDone() to return zero when
>> f/h released but move was not complete, or maybe it takes a few
>> ticks to set it properly.
>>
>> Is there anything else you'd like me to try?
>>
>> BTW, we are still using firmware 433q.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 12:31 PM, Hardy Family
>> <hardy.woodland.cypress@...> wrote:
>>
>> Hi Tom,
>>
>> Yes, it seems to always fail on the 2nd F/H. The *exact* code is
>> rather too complicated to post here, since our build system pulls in
>> code from various places to build the executable for various machine
>> configurations. There is also a supervisor running in another
>> thread, which shouldn't really matter, but it's possible that it is
>> interfering somehow.
>>
>> Let me research this a bit more and I'll get back to you. One thing
>> that might be relevant is that we are actually using the following
>> function instead of the simple 'wait_done' in my original post.
>>
>> int CheckNearlyDone(unsigned axis)
>> {
>> TRIP_COEFF * p = chan[axis].pcoeff;
>> if (CheckDoneFH(axis) || !p)
>> return 1; // Fully Done
>> // Look backwards thru current trip states, before current one.
>> If any are
>> // constant velocity, we must now be decelerating, so nearly
>> done.
>> while (--p > chan[axis].c)
>> if (p->a == 0. && p->b == 0.)
>> return -1; // No t^2 or t^3 coeffs, so must be constant
>> velocity
>> return 0;
>> }
>>
>> so maybe it's this trickiness with checking for pcoeff which is
>> making it break out of the wait prematurely. I'm in the middle of
>> something else at the moment, but probably need to rethink the use
>> of StopState in the above.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 10:16 AM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> It seems to work ok for one axis for me. How can the routine be
>> returning with stopping state 2 if it only returns when stopping
>> state is 0?
>>
>> Is it failing always on the 2nd feedhold? or only sometimes?
>>
>> Can you post the exact code you are running?
>>
>> This seems to work for me:
>>
>> #include "KMotionDef.h"
>>
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> MoveRel(1,300000);
>> while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> Regards
>>
>> TK
>>
>> On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@...
>> [DynoMotion] wrote:
>>
>> Thanks, that's a big improvement. I added the check for
>> CS0_StoppingState==0 and it works. Unfortunately, it only works for
>> the first feed hold. If I press f/h a second time in the same
>> motion command, it somehow exits the CheckDoneFH loop and yet the
>> stopping state is 2. Maybe there is a moment where CheckDone() is
>> true and stopping state is 0, prior to setting the stopping state
>> non-zero again.
>>
>> Maybe I have a race condition. This move is two axis (X,Y) so the
>> mask is 0x3 in my wait_done() function.
>>
>> Regards,
>> SJH
>>
>> On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> You might try waiting for CheckDone and not Feedhold like in the
>> code below.
>>
>> Feedhold should make the Axis Done after stopping, but FeedHold will
>> be present. Release of Feedhold should automatically re target the
>> Axes to the original destination.
>>
>> HTH
>>
>> Regards
>>
>> TK
>>
>> #include "KMotionDef.h"
>>
>> //wait for Done and not FeedHold
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> while (!CheckDoneFH(0)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@...
>> [DynoMotion] wrote:
>>
>> Hi Tom,
>>
>> I have some kflop code to move the axes when operating our tool
>> changer. It calls Move() then checks for completion in a loop using
>> CheckDone(). Unfortunately this doesn't work nicely if the PC
>> application sends a feed hold. If it does, then CheckDone() returns
>> non-zero rather than continuing to return 0 until the f/h is
>> released and the move completes.
>>
>> Am I using this correctly? Ideally, it would be nice to accept f/h
>> during the tool change since it gives the user a chance to load
>> tools etc. if they notice something is wrong. Otherwise, it would
>> be acceptable to somehow inhibit any f/h or overrides. As it is,
>> interrupting any of the move segments generates an error when the
>> code checks that the move really is complete.
>>
>> Just in case it's a snafu on my part, here is the code being used:
>>
>> void wait_done(unsigned axis_mask)
>> {
>> unsigned i;
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDone(i))
>> axis_mask &= ~(1u<<i);
>> }
>> }
>>
>> int check_error()
>> {
>> if (*supe->estop_state) {
>> printf("Estop in tool change\n");
>> return 1; // estop is like a cancel
>> }
>> if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
>> printf("Axis disabled in tool change\n");
>> return 2; // usually following error
>> }
>> if (CS0_StoppingState) {
>> printf("Stopping state %d in tool change\n",
>> CS0_StoppingState);
>> return 3;
>> }
>> return 0;
>> }
>>
>> void move_z(double z)
>> {
>> Move(2, z);
>> wait_done(1u<<2);
>> }
>>
>> int move_z_safe()
>> {
>> // Move to near max Z position (safest for moving to/from work,
>> and manual changes)
>> move_z(SAFE_LEVEL);
>> return check_error();
>> }
>>
>> Regards,
>> SJH
>
>
>
> Links:
> ------
> [1]
> https://groups.yahoo.com/neo/groups/DynoMotion/conversations/messages/14742;_ylc=X3oDMTJyYjlwNHM0BF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRtc2dJZAMxNDc0MgRzZWMDZnRyBHNsawNycGx5BHN0aW1lAzE0OTQ2MzU3OTc-?act=reply&messageNum=14742
> [2]
> https://groups.yahoo.com/neo/groups/DynoMotion/conversations/newtopic;_ylc=X3oDMTJmdGRucWhrBF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDZnRyBHNsawNudHBjBHN0aW1lAzE0OTQ2MzU3OTc-
> [3]
> https://groups.yahoo.com/neo/groups/DynoMotion/conversations/topics/14714;_ylc=X3oDMTM3aGZqbTlvBF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRtc2dJZAMxNDc0MgRzZWMDZnRyBHNsawN2dHBjBHN0aW1lAzE0OTQ2MzU3OTcEdHBjSWQDMTQ3MTQ-
> [4] https://yho.com/1wwmgg
> [5]
> https://groups.yahoo.com/neo/groups/DynoMotion/info;_ylc=X3oDMTJmY3RlaWs0BF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDdnRsBHNsawN2Z2hwBHN0aW1lAzE0OTQ2MzU3OTc-
> [6]
> https://groups.yahoo.com/neo/groups/DynoMotion/members/all;_ylc=X3oDMTJnZzQxaGRuBF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDdnRsBHNsawN2bWJycwRzdGltZQMxNDk0NjM1Nzk3
> [7]
> https://groups.yahoo.com/neo;_ylc=X3oDMTJldjNncnQ2BF9TAzk3NDc2NTkwBGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDZnRyBHNsawNnZnAEc3RpbWUDMTQ5NDYzNTc5Nw--
> [8] https://info.yahoo.com/privacy/us/yahoo/groups/details.html
> [9] https://info.yahoo.com/legal/us/yahoo/utos/terms/
|
|